#ifndef EFFORT_VISUAL_H
#define EFFORT_VISUAL_H

#include <sensor_msgs/JointState.h>

namespace Ogre
{
class Vector3;
class Quaternion;
}

namespace urdf
{
class Model;
}

namespace rviz
{
class Arrow;
class BillboardLine;
}

namespace rviz
{
// Each instance of EffortVisual represents the visualization of a single
// sensor_msgs::Effort message.  Currently it just shows an arrow with
// the direction and magnitude of the acceleration vector, but could
// easily be expanded to include more of the message data.
class EffortVisual
{
public:
  // Constructor.  Creates the visual stuff and puts it into the
  // scene, but in an unconfigured state.
  EffortVisual(Ogre::SceneManager* scene_manager,
               Ogre::SceneNode* parent_node,
               boost::shared_ptr<urdf::Model> urdf_model);

  // Destructor.  Removes the visual stuff from the scene.
  virtual ~EffortVisual();

  // set rainbow color
  void getRainbowColor(float value, Ogre::ColourValue& color);
  // Configure the visual to show the data in the message.
  void setMessage(const sensor_msgs::JointStateConstPtr& msg);

  // Set the pose of the coordinate frame the message refers to.
  // These could be done inside setMessage(), but that would require
  // calls to FrameManager and error handling inside setMessage(),
  // which doesn't seem as clean.  This way EffortVisual is only
  // responsible for visualization.
  void setFramePosition(const Ogre::Vector3& position);
  void setFrameOrientation(const Ogre::Quaternion& orientation);

  // set the pose of coordinates frame the each joint refers to.
  void setFramePosition(const std::string joint_name, const Ogre::Vector3& position);
  void setFrameOrientation(const std::string joint_name, const Ogre::Quaternion& orientation);

  void setFrameEnabled(const std::string joint_name, const bool e);

  // Set the color and alpha of the visual, which are user-editable
  // parameters and therefore don't come from the Effort message.
  void setColor(float r, float g, float b, float a);

  void setWidth(float w);

  void setScale(float s);

private:
  // The object implementing the effort circle
  std::map<std::string, rviz::BillboardLine*> effort_circle_;
  std::map<std::string, rviz::Arrow*> effort_arrow_;
  std::map<std::string, bool> effort_enabled_;

  // A SceneNode whose pose is set to match the coordinate frame of
  // the Effort message header.
  Ogre::SceneNode* frame_node_;

  // The SceneManager, kept here only so the destructor can ask it to
  // destroy the ``frame_node_``.
  Ogre::SceneManager* scene_manager_;

  std::map<std::string, Ogre::Vector3> position_;
  std::map<std::string, Ogre::Quaternion> orientation_;

  float width_, scale_;

  // The object for urdf model
  boost::shared_ptr<urdf::Model> urdf_model_;
};

} // end namespace rviz

#endif // EFFORT_VISUAL_H
